import { RecorderTypeEnum } from './types.d'

interface ChatAudioPlayerParmas {
  play?: () => number
  pause?: () => number
  resume?: () => number
  destroy?: () => number
  onProcess?: (currentTime: number, duration: number) => void
}

class ChatAudioPlayer {
  private static instance: ChatAudioPlayer
  private audio: HTMLAudioElement | null
  private status: RecorderTypeEnum
  private cb?: ChatAudioPlayerParmas

  constructor() {
    this.status = RecorderTypeEnum.end
    this.audio = new Audio()
  }

  public static getInstance(): ChatAudioPlayer {
    if (!ChatAudioPlayer.instance) {
      ChatAudioPlayer.instance = new ChatAudioPlayer()
    }
    return ChatAudioPlayer.instance
  }

  public play(audioUrl: string, params?: ChatAudioPlayerParmas): void {
    // 如果存在先销毁
    if (this.status != RecorderTypeEnum.end) {
      this.destroy()
    }

    this.audio = new Audio()
    this.audio.src = audioUrl
    this.audio.play()

    this.cb = params
    this.status = RecorderTypeEnum.start
    this.addEvent('timeupdate', this.onProcess)
    this.cb?.play?.()
  }

  public pause(): void {
    this.audio?.pause?.()
    this.status = RecorderTypeEnum.pause
    this.removeEvent('timeupdate', this.onProcess)
    this.cb?.pause?.()
  }

  public resume(): void {
    this.audio?.play?.()
    this.status = RecorderTypeEnum.start
    this.addEvent('timeupdate', this.onProcess)
    this.cb?.resume?.()
  }

  public destroy(): void {
    if (this.audio) {
      this.audio.pause?.()
      this.audio.currentTime = 0
      this.audio = null

      this.status = RecorderTypeEnum.end
      this.removeEvent('timeupdate', this.onProcess)
      this.cb?.destroy?.()
    }
  }

  public onProcess = () => {
    const currentTime = this.audio?.currentTime
    const duration = this.audio?.duration
    this.cb?.onProcess?.(currentTime || 0, duration || 0)

    // 播放完毕
    if (currentTime == duration) {
      this.destroy()
    }
  }

  public addEvent(name: string, cd: () => void) {
    if (name) {
      this.audio?.addEventListener?.(name, cd)
    }
  }

  public removeEvent(name: string, cd: () => void) {
    if (name) {
      this.audio?.removeEventListener?.(name, cd)
    }
  }
}

export default ChatAudioPlayer
